package ph.com.gs3.formalistics;

import ph.com.gs3.formalistics.fragments.views.LoginViewFragment;
import ph.com.gs3.formalistics.fragments.views.SplashViewFragment;
import ph.com.gs3.formalistics.fragments.workers.LoginWorkerFragment;
import ph.com.gs3.formalistics.managers.SessionManager.LoginResult;
import ph.com.gs3.formalistics.model.dao.UserAccountsDAO;
import ph.com.gs3.formalistics.model.valueobjects.business.User;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class LoginActivity extends Activity implements LoginViewFragment.LoginActionsListener,
        LoginWorkerFragment.SignInCallback {

	// UI Fragments
	private LoginViewFragment loginFragment;
	private SplashViewFragment splashFragment;

	// Task Fragments
	private LoginWorkerFragment loginWorkerFragment;

	// Data Access Objects
	private UserAccountsDAO userAccountsDAO;

	public static final String FRAGMENT_TITLE_LOGIN = "Login to Formalistics";
	public static final String FRAGMENT_TITLE_SPLASH = "Formalistics";

	public static enum Status {
		NEEDS_REAUTHENTICATION, APPLICATION_ERROR, NORMAL
	}

	public static final String EXTRA_STATUS = "status";
	public static final String EXTRA_LOGIN_RESULT = "login_result";

	// ========================================================================
	// Extra Fields

	private Status status;
	private LoginResult loginResult;

	// ========================================================================
	// View Methods

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_login);

		initializeExtras();

		// initialize the fragments
		loginFragment = new LoginViewFragment();
		splashFragment = new SplashViewFragment();

		// initially show splash view
		setFragment(splashFragment, FRAGMENT_TITLE_SPLASH);

		// have the application decide if it needs to show the login view or it can
		// directly go to the main view
		navigateOrShowLogin();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.login, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	public void setFragment(Fragment fragment, String title) {

		FragmentTransaction transaction = getFragmentManager().beginTransaction();
		transaction.replace(R.id.container, fragment);

		transaction.commit();
		setTitle(title);
	}

	// ========================================================================
	// Functional Methods

	private void initializeExtras() {
		Bundle extras = getIntent().getExtras();

		status = Status.NORMAL;
		loginResult = null;

		if (extras != null) {
			if (extras.containsKey(EXTRA_STATUS)) {
				status = (Status) extras.get(EXTRA_STATUS);
			}

			if (extras.containsKey(EXTRA_LOGIN_RESULT)) {
				loginResult = (LoginResult) extras.get(EXTRA_LOGIN_RESULT);
			}

		}
	}

	private void navigateOrShowLogin() {

		// lazy load UserAccountsDAO object
		if (userAccountsDAO == null) {
			userAccountsDAO = new UserAccountsDAO(LoginActivity.this);
		}

		userAccountsDAO.open();
		User activeUser = userAccountsDAO.getActiveUserAccount();
		userAccountsDAO.close();

		if (activeUser != null && status == Status.NORMAL) {
			// TODO: check if the active user can be passed to the main activity instead
			// of having it lookup again.
			navigateToMainActivity(activeUser);
		} else {
			showLoginFragment();
		}

	}

	private void showLoginFragment() {

		// initialize the worker fragment its if not yet initialized
		FragmentManager fragmentMan = getFragmentManager();
		loginWorkerFragment = (LoginWorkerFragment) fragmentMan
		        .findFragmentByTag(LoginWorkerFragment.TAG);

		if (loginWorkerFragment == null) {
			loginWorkerFragment = new LoginWorkerFragment();
			fragmentMan.beginTransaction().add(loginWorkerFragment, LoginWorkerFragment.TAG)
			        .commit();
		}

		setFragment(loginFragment, FRAGMENT_TITLE_LOGIN);

		// check if this method is called with the need to reauthenticate
		if (status != Status.NORMAL && loginResult != null) {
			loginFragment.setErrorMessage(loginResult.message);
		}

	}

	private void navigateToMainActivity(User activeUser) {

		// start the main activity and close this activity
		Intent mainActivity = new Intent(LoginActivity.this, MainActivity.class);
		mainActivity.putExtra(MainActivity.EXTRA_ACTIVE_USER, activeUser);
		startActivity(mainActivity);
		finish();

	}

	// ========================================================================
	// Implementation Methods

	@Override
	public void onSignIn(String server, String email, String password) {

		if (splashFragment == null) {
			splashFragment = new SplashViewFragment();
		}

		setFragment(splashFragment, FRAGMENT_TITLE_SPLASH);
		splashFragment.setLoadingMessage("Logging in to server");

		loginWorkerFragment.signIn(server, email, password);
	}

	@Override
	public void onSignInSuccess(User activeUser) {

		navigateToMainActivity(activeUser);

	}

	@Override
	public void onSignInFail(String failureMessage) {
		setFragment(loginFragment, FRAGMENT_TITLE_LOGIN);
		loginFragment.setErrorMessage(failureMessage);
	}

}
